package org.mytool.common.db;

//import org.omg.CORBA.Object;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class DbWhere implements Serializable{
	protected String orderByClause;

	protected boolean distinct;

	protected List<Criteria> oredCriteria;

	protected Map<String,Object> param = new HashMap<String, Object>();//参数数据

	protected final String WHERE_COLNAME_PREX="whereColNamePrex";

	public DbWhere() {
		oredCriteria = new ArrayList<Criteria>();
	}

	public void setOrderByClause(String orderByClause) {
		this.orderByClause = orderByClause;
	}

	public String getOrderByClause() {
		return orderByClause;
	}

	public void setDistinct(boolean distinct) {
		this.distinct = distinct;
	}

	public boolean isDistinct() {
		return distinct;
	}

	public List<Criteria> getOredCriteria() {
		return oredCriteria;
	}

	public void or(Criteria criteria) {
		oredCriteria.add(criteria);
	}

	public Criteria or() {
		Criteria criteria = createCriteriaInternal();
		oredCriteria.add(criteria);
		return criteria;
	}

	public Criteria createCriteria() {
		Criteria criteria = createCriteriaInternal();
		if (oredCriteria.size() == 0) {
			oredCriteria.add(criteria);
		}
		return criteria;
	}

	protected Criteria createCriteriaInternal() {
		Criteria criteria = new Criteria();
		return criteria;
	}

	public void clear() {
		oredCriteria.clear();
		orderByClause = null;
		distinct = false;
	}

	protected abstract static class GeneratedCriteria <T>{
		protected List<Criterion> criteria;

		protected GeneratedCriteria() {
			criteria = new ArrayList<Criterion>();
		}

		public boolean isValid() {
			return criteria.size() > 0;
		}

		public List<Criterion> getAllCriteria() {
			return criteria;
		}

		public List<Criterion> getCriteria() {
			return criteria;
		}

		protected void addCriterion(String condition) {
			if (condition == null) {
				throw new RuntimeException("Value for condition cannot be null");
			}
			// criteria.add(new Map(condition));
			criteria.add(new Criterion(condition));
		}

		protected void addCriterion(String condition, T value,
				String property) {
			if (value == null) {
				throw new RuntimeException("Value for " + property
						+ " cannot be null");
			}
			// criteria.add(new Map(condition, value));
			criteria.add(new Criterion(condition, value,property));
		}


		protected void addCriterion(String condition, List<T> value,
									String property) {
			if (value == null) {
				throw new RuntimeException("Value for " + property
						+ " cannot be null");
			}
			// criteria.add(new Map(condition, value));
			criteria.add(new Criterion(condition, value,property));
		}

		protected void addCriterion(String condition, T value1,
									T value2, String property) {
			if (value1 == null || value2 == null) {
				throw new RuntimeException("Between values for " + property
						+ " cannot be null");
			}
			criteria.add(new Criterion(condition, value1, value2,property));
			// criteria.add(new HashMap());
		}

		public Criteria andIsNull(String colName) {
			addCriterion(colName + " is null");
			return (Criteria) this;
		}

		public Criteria andIsNotNull(String colName) {
			addCriterion(colName + " is not null");
			return (Criteria) this;
		}

		public Criteria andEqualTo(String colName, T value) {
			addCriterion(colName + " =", value, colName);
			return (Criteria) this;
		}

		public Criteria andNotEqualTo(String colName, T value) {
			addCriterion(colName + " <>", value, colName);
			return (Criteria) this;
		}

		public Criteria andGreaterThan(String colName, T value) {
			addCriterion(colName + " >", value, colName);
			return (Criteria) this;
		}

		public Criteria andGreaterThanOrEqualTo(String colName, T value) {
			addCriterion(colName + " >=", value, colName);
			return (Criteria) this;
		}

		public Criteria andLessThan(String colName, T value) {
			addCriterion(colName + " <", value, colName);
			return (Criteria) this;
		}

		public Criteria andLessThanOrEqualTo(String colName, T value) {
			addCriterion(colName + " <=", value, colName);
			return (Criteria) this;
		}

		public Criteria andLike(String colName, T value) {
			addCriterion(colName + " like", value, colName);
			return (Criteria) this;
		}

		public Criteria andNotLike(String colName, T value) {
			addCriterion(colName + " not like", value, colName);
			return (Criteria) this;
		}

		public Criteria andIn(String colName, List<T> values) {
//		public Criteria andIn(String colName,E values) {
			addCriterion(colName + " in", values, colName);
			return (Criteria) this;
		}

		public Criteria andNotIn(String colName, List<T> values) {
			addCriterion(colName + " not in", values, colName);
			return (Criteria) this;
		}

		public Criteria andBetween(String colName, T value1, T value2) {
			addCriterion(colName + " between", value1, value2, colName);
			return (Criteria) this;
		}

		public Criteria andNotBetween(String colName, T value1,
									  T value2) {
			addCriterion(colName + " not between", value1, value2, colName);
			return (Criteria) this;
		}
	}

	public static class Criteria extends GeneratedCriteria {

		protected Criteria() {
			super();
		}
	}

	public static class Criterion <T>{
		private String condition;

		private T value;

		private T secondValue;

		private boolean noValue;

		private boolean singleValue;

		private boolean betweenValue;

		private boolean listValue;

		private String typeHandler;

		private String colName;

		public String getCondition() {
			return condition;
		}

		public Object getValue() {
			return value;
		}

		public Object getSecondValue() {
			return secondValue;
		}

		public boolean isNoValue() {
			return noValue;
		}

		public boolean isSingleValue() {
			return singleValue;
		}

		public boolean isBetweenValue() {
			return betweenValue;
		}

		public boolean isListValue() {
			return listValue;
		}

		public String getTypeHandler() {
			return typeHandler;
		}

		protected Criterion(String condition) {
			super();
			this.condition = condition;
			this.typeHandler = null;
			this.noValue = true;
			this.colName = null;
		}




		 protected Criterion(String condition, T value, String typeHandler,String colName) {
			super();
			this.condition = condition;
			this.value = value;
			this.typeHandler = typeHandler;
			if (value instanceof List<?>) {
				this.listValue = true;
			} else {
				this.singleValue = true;
			}
			this.colName = colName;
		}


		protected Criterion(String condition, T value,String colName) {
			this(condition, value, "" ,colName);
		}


		protected Criterion(String condition, T value, T secondValue,
				String typeHandler,String colName) {
			super();
			this.condition = condition;
			this.value = value;
			this.secondValue = secondValue;
			this.typeHandler = typeHandler;
			this.betweenValue = true;
			this.colName = colName;
		}

		protected Criterion(String condition, T value, T secondValue,String colName) {
			this(condition, value, secondValue, null,colName);
		}
	}
	
	public String toWhereString(){
		StringBuilder sb = new StringBuilder();
		int countAnd = 0;
		List<Criteria> list = this.oredCriteria;
		
		if(list!=null && list.size()>0){
			sb.append(" where  ");
			int i=0;
			for (Criteria criteria:list) {
				if(i>0){
					sb.append(" or ");
				}
				sb.append(" ( ");
				List<Criterion> listCriterion = criteria.criteria;
				countAnd = 0;
				for(Criterion criterion:listCriterion){
					if(countAnd>0){
						sb.append(" and ");
					}
					if(criterion.noValue){
						sb.append(criterion.condition);
					}
					if(criterion.singleValue){
//						sb.append(criterion.condition).append(" '").append(criterion.value).append("' ");
						sb.append(criterion.condition).append(" :").append(WHERE_COLNAME_PREX+criterion.colName).append(" ");
						param.put(WHERE_COLNAME_PREX+criterion.colName,criterion.value);
					}
					if(criterion.betweenValue){
//						sb.append(criterion.condition).append(" '").append(criterion.value).append("' and '").append(criterion.secondValue).append("' ");
						sb.append(criterion.condition).append(" :").append(WHERE_COLNAME_PREX+criterion.colName+"1").append(" and :").append(WHERE_COLNAME_PREX+criterion.colName+"2").append(" ");
						param.put(WHERE_COLNAME_PREX+criterion.colName+"1",criterion.value);
						param.put(WHERE_COLNAME_PREX+criterion.colName+"2",criterion.secondValue);
					}
					if(criterion.listValue){
						sb.append(criterion.condition);
						List<String> list3 = (List)criterion.value;
						sb.append(" ( ");
						int j=0;
						for(String listItem :list3){
							if(j>0){
								sb.append(",");
							}
							//sb.append(listItem);
							sb.append(" :").append(WHERE_COLNAME_PREX+criterion.colName+j);
						    param.put(WHERE_COLNAME_PREX+criterion.colName+j,listItem);
							j++;
						}
						sb.append(" ) ");
//						sb.append(" and ").append(criterion.condition).append(" '").append(criterion.value).append("' ");
//						sb.append(" and ").append(criterion.condition).append(" :").append(WHERE_COLNAME_PREX+criterion.colName);
//						param.put(WHERE_COLNAME_PREX+criterion.colName,criterion.value);
					}
					
					countAnd++;
				}
				sb.append(" ) ");
				i++;
			}
			//System.out.println("i:"+i+" countAnd:"+countAnd);
			/*if(i>0 || countAnd >0){
				sb.insert(0, " where ");	
			}*/
			if(i ==1 && countAnd==0){
				return "";
			}
			
		}
		
		return sb.toString();
	}

	public Map<String,Object> getParamData(){
		return param;
	}
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		DbWhere example = new DbWhere();
		GeneratedCriteria c = example.createCriteria().andEqualTo("id", "123")
				.andEqualTo("name", "wangc").andBetween("create_date", "sss1", "ss2");
		List<Criterion> list = c.getAllCriteria();
		for(Criterion s : list){
			System.out.println(s.getTypeHandler()+" "+s.getCondition()+" "+s.getValue()+" "+s.getSecondValue());
		}
		
		System.out.println(example.toWhereString());
		
		DbWhere example2 = new DbWhere();
		example2.createCriteria();
		System.out.println("example2:"+example2.toWhereString());
		System.out.println("example2:"+example2.toWhereString());
		
	}
}
